home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 3
/
Gold Medal Software - Volume 3 (Gold Medal) (1994).iso
/
archive
/
cx201e.arj
/
CXSUB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-01
|
7KB
|
282 lines
/*
CXSUB functions.
Copyright (c) 1990-1994 Eugene Nelson, Four Lakes Computing.
This file contains useful subroutines that may be used with Cx.
See files CXSUB.DOC and CXSUB.H for interface information.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include "cxsub.h"
/*-----------------------------------------------------------------------*/
char *cx_error_message(
CXINT err)
{
switch (err)
{
case CX_ERR_INVALID: return ("data could not be decompressed");
case CX_ERR_METHOD: return ("invalid compression method");
case CX_ERR_BUFFSIZE: return ("invalid buffer size");
case CX_ERR_TEMPSIZE: return ("invalid temp buffer size");
case CXSUB_ERR_OPENS: return ("could not open source");
case CXSUB_ERR_OPEND: return ("could not open destination");
case CXSUB_ERR_NOMEM: return ("insufficient memory");
case CXSUB_ERR_READ: return ("could not read from source");
case CXSUB_ERR_WRITE: return ("could not write to destination");
case CXSUB_ERR_CLOSE: return ("could not close destination");
case CXSUB_ERR_INVALID: return ("source file is invalid or corrupt");
}
return ("unknown");
}
/*
The following define and routine
CX_FILESUB_RET
cx_filesub_error
Are used to release allocated memory.
*/
#define CX_FILESUB_RET(n) return(cx_filesub_error(n, ibuff, obuff, tbuff))
/*----------------------------------------------------------------------*/
static CXINT cx_filesub_error(
CXINT err,
CXBUFF ibuff,
CXBUFF obuff,
CXBUFF tbuff)
{
if (ibuff != NULL) free(ibuff);
if (obuff != NULL) free(obuff);
if (tbuff != NULL) free(tbuff);
return (err);
}
/*----------------------------------------------------------------------*/
CXINT cx_compress_ofile(
int ofile,
int ifile,
CXINT method,
CXINT bsize,
CXINT tsize,
int (*callback)(void *),
void *p)
{
CXBUFF ibuff = NULL;
CXBUFF obuff = NULL;
CXBUFF tbuff = NULL;
CXINT j, k, crc;
CXBUFF t;
ibuff = (CXBUFF) malloc(bsize);
obuff = (CXBUFF) malloc(bsize+CX_SLOP);
tbuff = (CXBUFF) malloc(tsize);
if ((ibuff == NULL) || (obuff == NULL) || (tbuff == NULL))
CX_FILESUB_RET (CXSUB_ERR_NOMEM);
while (1)
{
if (callback != NULL)
if (callback(p) != 0)
return (0);
j = read(ifile, ibuff, bsize);
if (j == 0xffff)
CX_FILESUB_RET (CXSUB_ERR_READ);
if (write(ofile, &j, CXINTSIZE) != CXINTSIZE)
CX_FILESUB_RET (CXSUB_ERR_WRITE);
if (j == 0)
break;
k = CX_COMPRESS(method, obuff, bsize, ibuff, j, tbuff, tsize);
if (k > j)
CX_FILESUB_RET (k);
if (write(ofile, &k, CXINTSIZE) != CXINTSIZE)
CX_FILESUB_RET (CXSUB_ERR_WRITE);
if (k == j) /* if block could not be compressed */
t = ibuff;
else
t = obuff;
crc = CX_CRC(t, k);
if (write(ofile, &crc, CXINTSIZE) != CXINTSIZE)
CX_FILESUB_RET (CXSUB_ERR_WRITE);
if (write(ofile, t, k) != k)
CX_FILESUB_RET (CXSUB_ERR_WRITE);
}
CX_FILESUB_RET (0);
}
/*----------------------------------------------------------------------*/
CXINT cx_compress_file(
char *dst,
char *src,
CXINT method,
CXINT bsize,
CXINT tsize,
int (*callback)(void *),
void *p)
{
int ifile = -1;
int ofile = -1;
CXINT j, k;
if ((ifile = open(src, O_RDWR|O_BINARY, 0)) == -1)
return (CXSUB_ERR_OPENS);
unlink(dst);
if ((ofile = open(dst, O_WRONLY|O_CREAT|O_BINARY, S_IREAD|S_IWRITE)) == -1)
{
close(ifile);
return (CXSUB_ERR_OPEND);
}
k = cx_compress_ofile(ofile, ifile, method, bsize, tsize, callback, p);
close(ifile);
j = (close(ofile) == 0? 0: CXSUB_ERR_CLOSE);
return (k==0? j: k);
}
/*----------------------------------------------------------------------*/
CXINT cx_decompress_ofile(
int ofile,
int ifile,
int (*callback)(void *),
void *p)
{
CXBUFF ibuff = NULL;
CXBUFF obuff = NULL;
CXBUFF tbuff = NULL;
CXINT bsize;
CXINT j, k, crc;
CXBUFF t;
if ((tbuff = (CXBUFF) malloc(CX_D_MINTEMP)) == NULL)
CX_FILESUB_RET (CXSUB_ERR_NOMEM);
bsize = 0;
while (1)
{
if (callback != NULL)
if (callback(p) != 0)
return (0);
if (read(ifile, &j, CXINTSIZE) != CXINTSIZE)
CX_FILESUB_RET (CXSUB_ERR_READ);
if (j == 0) /* This indicates the end of file */
break;
if (bsize < j)
{
bsize = j;
ibuff = (CXBUFF) realloc(obuff, bsize+CX_SLOP);
obuff = (CXBUFF) realloc(obuff, bsize);
if ((ibuff == NULL) || (obuff == NULL))
CX_FILESUB_RET (CXSUB_ERR_NOMEM);
}
if (read(ifile, &k, CXINTSIZE) != CXINTSIZE)
CX_FILESUB_RET (CXSUB_ERR_READ);
if ((k > j) || (k > bsize) || (j > bsize))
CX_FILESUB_RET (CXSUB_ERR_INVALID);
if (read(ifile, &crc, CXINTSIZE) != CXINTSIZE)
CX_FILESUB_RET (CXSUB_ERR_READ);
if (read(ifile, ibuff, k) != k)
CX_FILESUB_RET (CXSUB_ERR_READ);
if (CX_CRC(ibuff, k) != crc)
CX_FILESUB_RET (CXSUB_ERR_INVALID);
if (j == k) /* if block is not compressed */
t = ibuff;
else
{
k = CX_DECOMPRESS(obuff, bsize, ibuff, k, tbuff, CX_D_MINTEMP);
if (k > CX_MAX_BUFFER)
CX_FILESUB_RET (k);
if (j != k)
CX_FILESUB_RET (CXSUB_ERR_INVALID);
t = obuff;
}
if (ofile != -1)
if (write(ofile, t, j) != j)
CX_FILESUB_RET (CXSUB_ERR_WRITE);
}
CX_FILESUB_RET (0);
}
/*----------------------------------------------------------------------*/
CXINT cx_decompress_file(
char *dst,
char *src,
int (*callback)(void *),
void *p)
{
int ifile = -1;
int ofile = -1;
CXINT k, j;
if ((ifile = open(src, O_RDWR|O_BINARY, 0)) == -1)
return (CXSUB_ERR_OPENS);
if (dst != NULL)
{
unlink(dst);
if ((ofile = open(dst, O_WRONLY|O_CREAT|O_BINARY, S_IREAD|S_IWRITE)) == -1)
{
close(ifile);
return (CXSUB_ERR_OPEND);
}
}
k = cx_decompress_ofile(ofile, ifile, callback, p);
close(ifile);
if (dst != NULL)
j = (close(ofile) == 0? 0: CXSUB_ERR_CLOSE);
else
j = 0;
return (k==0? j: k);
}